package vertx.starter.rx;

import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.reactivex.core.AbstractVerticle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vertx.starter.rx.db.DatabaseService;

import java.util.List;

/**
 * there is sub route testing with failed.
 */
public class HttpServerVerticle extends AbstractVerticle {

    private static final
    Logger LOGGER = LoggerFactory.getLogger(HttpServerVerticle.class);

    public static final String CONFIG_HTTP_SERVER_PORT = "http.server.port";
    public static final String CONFIG_WIKIDB_QUEUE = "wikidb.queue";

    private DatabaseService dbService;

    @Override
    public void start(Promise<Void> promise) throws Exception {
        // FIXME： rx-java with vertx by getDelegate()
        String wikiDbQueue = config().getString(CONFIG_WIKIDB_QUEUE, "wikidb.queue");
        dbService = DatabaseService.createProxy(vertx.getDelegate(), wikiDbQueue);

        Router router = Router.router(vertx.getDelegate());
        router.get("/page").handler(this::queryHandler);
        router.post().handler(BodyHandler.create());
        router.post("/create").handler(this::createHandler);
        router.delete("/").handler(this::deleteHandler);

        int port = config().getInteger(CONFIG_HTTP_SERVER_PORT, 8089);
        HttpServer server = vertx.getDelegate().createHttpServer();
        server
                .requestHandler(router)
                .listen(port, ar -> {
                    if (ar.succeeded()) {
                        LOGGER.info("HTTP server running on port: " + port);
                        promise.complete();
                    } else {
                        LOGGER.error("Could not start a HTTP server", ar.cause());
                        promise.fail(ar.cause());
                    }
                });

    }

    private void deleteHandler(RoutingContext routingContext) {

        String name = null;
        List<String> stringList = routingContext.queryParam("name");
        if (stringList != null && !stringList.isEmpty())
            name = stringList.get(0);
        dbService.deletePage(name, relpy -> {
            if (relpy.succeeded()) {
                Integer result = relpy.result();
                routingContext.response().end(result.toString());

            } else {
                routingContext.fail(relpy.cause());
            }

        });
    }

    private void createHandler(RoutingContext context) {
        JsonObject bodyAsJson = context.getBodyAsJson();
        Handler<AsyncResult<Integer>> handler = reply -> {
            if (reply.succeeded()) {
                context.response().setStatusCode(200);
                context.response().end(bodyAsJson.toBuffer());
            } else {
                context.fail(reply.cause());
            }
        };


        dbService.createPage(bodyAsJson.getString("name"), bodyAsJson.getString("content"), handler);
    }

    private void queryHandler(RoutingContext context) {
        dbService.fetchAllPages(reply -> {
            if (reply.succeeded()) {
                JsonArray body = reply.result();
                context.response().putHeader("Content-Type", "application/json");
                context.response().end(body.toString());

            } else {
                context.fail(reply.cause());
            }
        });


    }
}
